package com.dldata.devtools30.cfg;

import cn.hutool.core.io.FileUtil;
import com.dldata.devtools30.utils.DateUtil;
import com.dldata.devtools30.utils.Public;
import com.dldata.devtools30.utils.StringUtil;
import com.dldata.devtools30.utils.dataexport.DataExportUtil;
import com.dldata.devtools30.utils.dataexport.TableConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.CronTask;
import org.springframework.stereotype.Component;

import java.io.File;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Configuration
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@Component
@Slf4j
public class ZzBackupCbPlanConfigInfoExportTask implements Runnable,ApplicationListener<WebServerInitializedEvent> {
    
    private final static String backdirname="devtoolsbackup";

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    private ApplicationContext applicationContext;
    
    
    public void run() {
        
        String dataversion = DateUtil.formatFromDate("yyyyMMddHHmm", new Date());
        backupMetadata(dataversion);
        backupForm(dataversion);
        backupApi(dataversion);
        backupExcel(dataversion);
        backupZhiBiaoPlan(dataversion);
        backupZhiBiaoInfo(dataversion);
        backupZhiBiaoObj(dataversion);
        delFile();
    
        /**
         * 清理API日志
         */
        Calendar calendar=Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, Public.logstoredays*-1);
        jdbcTemplate.update(" delete devt_api_log where cdate < ? ",new Object[]{new Timestamp(calendar.getTimeInMillis())});
    }
    
    
    public void backupZhiBiaoInfo(String dataversion){
        List<TableConfig> tables = new LinkedList<>();
        
        TableConfig tableConfig = new TableConfig();
        tableConfig.setTablename("devt_zbclass_info");
        tableConfig.setTablenameZh("指标分类信息表");
        tableConfig.setFieldname("id");
        tableConfig.setFfieldname("");
        tableConfig.setSubtableList(new LinkedList<>());
        tables.add(tableConfig);
        
        //相关子表
        TableConfig configType = new TableConfig();
        configType.setTablename("devt_zbcfg_info");
        configType.setTablenameZh("指标配置信息表");
        configType.setFieldname("zbclassid");
        configType.setFfieldname("id");
        configType.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configType);
        
        HashMap<String, List<Object>> dataMap = new HashMap<>();
        String columsql = "SELECT * FROM " + tableConfig.getTablename();
        List<Map<String, Object>> list = jdbcTemplate.queryForList(columsql);
        List columList = list.stream().map(e -> e.get("ID")).collect(Collectors.toList());
        dataMap.put(tableConfig.getTablename(), columList);
        
        String tabledatas = DataExportUtil.createDataExportUtil(jdbcTemplate.getDataSource(),true).exportData(tables, dataMap,new ArrayList<>());
        String filename = ApplicationHome.getApplicationConfig()+ "/"+backdirname+"/"+dataversion+"/"+tableConfig.getTablename()+".sql";
        new File(filename).getParentFile().mkdirs();
        FileUtil.writeString(tabledatas, filename, Charset.forName("UTF-8"));
    }
    
    public void backupZhiBiaoObj(String dataversion){
        List<TableConfig> tables = new LinkedList<>();
        
        TableConfig tableConfig = new TableConfig();
        tableConfig.setTablename("devt_zbobj_info");
        tableConfig.setTablenameZh("指标对象信息表");
        tableConfig.setFieldname("id");
        tableConfig.setFfieldname("");
        tableConfig.setSubtableList(new LinkedList<>());
        tables.add(tableConfig);
        
        //相关子表
        TableConfig configType = new TableConfig();
        configType.setTablename("devt_zbobj_field");
        configType.setTablenameZh("指标对象指标字段绑定表");
        configType.setFieldname("zbobjid");
        configType.setFfieldname("id");
        configType.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configType);
        
        HashMap<String, List<Object>> dataMap = new HashMap<>();
        String columsql = "SELECT * FROM " + tableConfig.getTablename();
        List<Map<String, Object>> list = jdbcTemplate.queryForList(columsql);
        List columList = list.stream().map(e -> e.get("ID")).collect(Collectors.toList());
        dataMap.put(tableConfig.getTablename(), columList);
        
        String tabledatas = DataExportUtil.createDataExportUtil(jdbcTemplate.getDataSource(),true).exportData(tables, dataMap,new ArrayList<>());
        String filename = ApplicationHome.getApplicationConfig()+ "/"+backdirname+"/"+dataversion+"/"+tableConfig.getTablename()+".sql";
        new File(filename).getParentFile().mkdirs();
        FileUtil.writeString(tabledatas, filename, Charset.forName("UTF-8"));
    }
    
    public void backupZhiBiaoPlan(String dataversion){
        List<TableConfig> tables = new LinkedList<>();
        
        TableConfig tableConfig = new TableConfig();
        tableConfig.setTablename("devt_zbplan_info");
        tableConfig.setTablenameZh("动态指标集方案表");
        tableConfig.setFieldname("id");
        tableConfig.setFfieldname("");
        tableConfig.setSubtableList(new LinkedList<>());
        tables.add(tableConfig);
        
        //相关子表
        TableConfig configType = new TableConfig();
        configType.setTablename("devt_zbplan_type");
        configType.setTablenameZh("动态指标方案分类表");
        configType.setFieldname("id");
        configType.setFfieldname("typeid");
        configType.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configType);
        
        TableConfig configZhiBioaobj = new TableConfig();
        configZhiBioaobj.setTablename("devt_zbplan_zbobj");
        configZhiBioaobj.setTablenameZh("动态指标指标对象绑定");
        configZhiBioaobj.setFieldname("planid");
        configZhiBioaobj.setFfieldname("id");
        configZhiBioaobj.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configZhiBioaobj);
        
        TableConfig configZhiBioaItem = new TableConfig();
        configZhiBioaItem.setTablename("devt_zbplan_item");
        configZhiBioaItem.setTablenameZh("动态指标集指标绑定表");
        configZhiBioaItem.setFieldname("planid");
        configZhiBioaItem.setFfieldname("id");
        configZhiBioaItem.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configZhiBioaItem);
        
        TableConfig configZhiBioaPara = new TableConfig();
        configZhiBioaPara.setTablename("devt_zbplan_para");
        configZhiBioaPara.setTablenameZh("动态指标集查询参数表");
        configZhiBioaPara.setFieldname("planid");
        configZhiBioaPara.setFfieldname("id");
        configZhiBioaPara.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configZhiBioaPara);
        
        TableConfig configZhiBioaParaCxtj = new TableConfig();
        configZhiBioaParaCxtj.setTablenameZh("动态指标集查询参数表");
        configZhiBioaParaCxtj.setTablename("devt_zbplan_para");
        configZhiBioaParaCxtj.setFieldname("planid");
        configZhiBioaParaCxtj.setFfieldname("id");
        configZhiBioaParaCxtj.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configZhiBioaParaCxtj);
        
        HashMap<String, List<Object>> dataMap = new HashMap<>();
        String columsql = "SELECT * FROM " + tableConfig.getTablename();
        List<Map<String, Object>> list = jdbcTemplate.queryForList(columsql);
        List columList = list.stream().map(e -> e.get("ID")).collect(Collectors.toList());
        dataMap.put(tableConfig.getTablename(), columList);
        
        String tabledatas = DataExportUtil.createDataExportUtil(jdbcTemplate.getDataSource(),true).exportData(tables, dataMap,new ArrayList<>());
        String filename = ApplicationHome.getApplicationConfig()+ "/"+backdirname+"/"+dataversion+"/"+tableConfig.getTablename()+".sql";
        new File(filename).getParentFile().mkdirs();
        FileUtil.writeString(tabledatas, filename, Charset.forName("UTF-8"));
    }
    
    /**
     *
     * @param dataversion
     */
    public void backupApi(String dataversion){
        List<TableConfig> tables = new LinkedList<>();
        
        TableConfig tableConfig = new TableConfig();
        tables.add(tableConfig);
        tableConfig.setTablename("devt_api_type");
        tableConfig.setTablenameZh("AP业务表");
        tableConfig.setFieldname("id");
        tableConfig.setFfieldname("");
        tableConfig.setSubtableList(new LinkedList<>());
        
        //相关子表
        TableConfig configMain = new TableConfig();
        
        configMain.setTablename("devt_api_main");
        configMain.setTablenameZh("API功能分类表");
        configMain.setFieldname("flid");
        configMain.setFfieldname("id");
        configMain.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configMain);
        
        TableConfig configSub = new TableConfig();
        configSub.setTablename("devt_api_sub");
        configSub.setTablenameZh("API功能表");
        configSub.setFieldname("mainid");
        configSub.setFfieldname("id");
        configMain.getSubtableList().add(configSub);
    
        TableConfig config = new TableConfig();
        config.setTablename("devt_api_tjoptcheck");
        config.setTablenameZh("API参数校验配置");
        config.setFieldname("sub_id");
        config.setFfieldname("id");
        configSub.getSubtableList().add(config);
    
        config = new TableConfig();
        config.setTablename("devt_api_tjopt");
        config.setTablenameZh("API参数配置表");
        config.setFieldname("subid");
        config.setFfieldname("id");
        configSub.getSubtableList().add(config);

        HashMap<String, List<Object>> dataMap = new HashMap<>();
        String columsql = "SELECT * FROM " + tableConfig.getTablename();
        List<Map<String, Object>> list = jdbcTemplate.queryForList(columsql);
        List columList = list.stream().map(e -> e.get("ID")).collect(Collectors.toList());
        dataMap.put(tableConfig.getTablename(), columList);



        
        String tabledatas = DataExportUtil.createDataExportUtil(jdbcTemplate.getDataSource(),true).exportData(tables, dataMap,new ArrayList<>());
        String filename = ApplicationHome.getApplicationConfig()+ "/"+backdirname+"/"+dataversion+"/"+tableConfig.getTablename()+".sql";
        new File(filename).getParentFile().mkdirs();
        FileUtil.writeString(tabledatas, filename, Charset.forName("UTF-8"));
    }


    /**
     *
     * @param dataversion
     */
    public void backupExcel(String dataversion){
        List<TableConfig> tables = new LinkedList<>();

        TableConfig configExcel = new TableConfig();
        tables.add(configExcel);
        configExcel.setTablename("devt_excel");
        configExcel.setTablenameZh("EXCEL配置");
        configExcel.setFieldname("id");
        configExcel.setSubtableList(new LinkedList<>());

        TableConfig configExcelField = new TableConfig();
        configExcelField.setTablename("devt_excel_field");
        configExcelField.setTablenameZh("EXCEL字段对应配置");
        configExcelField.setFieldname("excel_id");
        configExcelField.setFfieldname("id");
        configExcel.getSubtableList().add(configExcelField);

        TableConfig configExcelType = new TableConfig();
        configExcelType.setTablename("devt_excel_type");
        configExcelType.setTablenameZh("EXCEL分类配置");
        configExcelType.setFieldname("id");
        configExcelType.setFfieldname("type_id");
        configExcel.getSubtableList().add(configExcelType);


        HashMap<String, List<Object>> dataMap = new HashMap<>();
        String columsqlExecl = "SELECT * FROM " + configExcel.getTablename();
        List<Map<String, Object>> listExcel = jdbcTemplate.queryForList(columsqlExecl);
        List columListExcel = listExcel.stream().map(e -> e.get("id")).collect(Collectors.toList());
        dataMap.put(configExcel.getTablename(), columListExcel);

        String tabledatas = DataExportUtil.createDataExportUtil(jdbcTemplate.getDataSource(),true).exportData(tables, dataMap,new ArrayList<>());
        String filename = ApplicationHome.getApplicationConfig()+ "/"+backdirname+"/"+dataversion+"/"+configExcel.getTablename()+".sql";
        new File(filename).getParentFile().mkdirs();
        FileUtil.writeString(tabledatas, filename, Charset.forName("UTF-8"));
    }

    /**
     *
     * @param dataversion
     */
    public void backupForm(String dataversion){
        List<TableConfig> tables = new LinkedList<>();
        
        TableConfig tableConfigType = new TableConfig();
        tables.add(tableConfigType);
        tableConfigType.setTablename("devt_form_type");
        tableConfigType.setTablenameZh("表单分类表");
        tableConfigType.setFieldname("id");
        tableConfigType.setFfieldname("");
        tableConfigType.setSubtableList(new LinkedList<>());
        
        //相关子表
        TableConfig configTable = new TableConfig();
        configTable.setTablename("devt_form_listtemplate");
        configTable.setTablenameZh("表单基础信息表");
        configTable.setFieldname("flid");
        configTable.setFfieldname("id");
        configTable.setSubtableList(new LinkedList<>());
        tableConfigType.getSubtableList().add(configTable);
        
        TableConfig config = new TableConfig();
        config.setTablename("devt_form_design");
        config.setTablenameZh("表单配置表");
        config.setFieldname("templateid");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
    
        config = new TableConfig();
        config.setTablename("devt_form_fieldconfig");
        config.setTablenameZh("表单配置字段表");
        config.setFieldname("templateid");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
    
        config = new TableConfig();
        config.setTablename("devt_form_listtempl_args");
        config.setTablenameZh("表单配置子表");
        config.setFieldname("templeid");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
    
        config = new TableConfig();
        config.setTablename("devt_form_listtempl_config");
        config.setTablenameZh("表单配置表");
        config.setFieldname("templeid");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
    
        config = new TableConfig();
        config.setTablename("devt_form_listtempl_otherbtn");
        config.setTablenameZh("表单配置其它按钮表");
        config.setFieldname("templeid");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
    
        config = new TableConfig();
        config.setTablename("devt_form_listtempl_theader");
        config.setTablenameZh("表单配置表头配置表");
        config.setFieldname("templeid");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
    
        config = new TableConfig();
        config.setTablename("devt_form_metadata");
        config.setTablenameZh("表单配置元数据表");
        config.setFieldname("templeid");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
        
        HashMap<String, List<Object>> dataMap = new HashMap<>();
        String columsql = "SELECT * FROM " + tableConfigType.getTablename();
        List<Map<String, Object>> list = jdbcTemplate.queryForList(columsql);
        List columList = list.stream().map(e -> e.get("ID")).collect(Collectors.toList());
        dataMap.put(tableConfigType.getTablename(), columList);
        
        String tabledatas = DataExportUtil.createDataExportUtil(jdbcTemplate.getDataSource(),true).exportData(tables, dataMap,new ArrayList<>());
        String filename = ApplicationHome.getApplicationConfig()+ "/"+backdirname+"/"+dataversion+"/"+tableConfigType.getTablename()+".sql";
        new File(filename).getParentFile().mkdirs();
        FileUtil.writeString(tabledatas, filename, Charset.forName("UTF-8"));
    }
    
    /**
     *
     * @param dataversion
     */
    public void backupMetadata(String dataversion){
        List<TableConfig> tables = new LinkedList<>();

        TableConfig tableConfig = new TableConfig();
        tables.add(tableConfig);
        tableConfig.setTablename("devt_model_metadata_type");
        tableConfig.setTablenameZh("元数据分类表");
        tableConfig.setFieldname("id");
        tableConfig.setFfieldname("");
        tableConfig.setSubtableList(new LinkedList<>());

        //相关子表
        TableConfig configTable = new TableConfig();
    
        configTable.setTablename("devt_model_metadata_table");
        configTable.setTablenameZh("元数据表");
        configTable.setFieldname("type_id");
        configTable.setFfieldname("id");
        configTable.setSubtableList(new LinkedList<>());
        tableConfig.getSubtableList().add(configTable);
    
        TableConfig config = new TableConfig();
        config.setTablename("devt_model_metadata_field");
        config.setTablenameZh("字段表");
        config.setFieldname("form_id");
        config.setFfieldname("id");
        configTable.getSubtableList().add(config);
        
        HashMap<String, List<Object>> dataMap = new HashMap<>();
        String columsql = "SELECT * FROM " + tableConfig.getTablename();
        List<Map<String, Object>> list = jdbcTemplate.queryForList(columsql);
        List columList = list.stream().map(e -> e.get("ID")).collect(Collectors.toList());
        dataMap.put(tableConfig.getTablename(), columList);

        String tabledatas = DataExportUtil.createDataExportUtil(jdbcTemplate.getDataSource(),true).exportData(tables, dataMap,new ArrayList<>());
        String filename = ApplicationHome.getApplicationConfig()+ "/"+backdirname+"/"+dataversion+"/"+tableConfig.getTablename()+".sql";
        new File(filename).getParentFile().mkdirs();
        FileUtil.writeString(tabledatas, filename, Charset.forName("UTF-8"));
    }
    
    
    //删除规定时间之前的数据
    public void delFile(){
        String property = applicationContext.getEnvironment().getProperty("server.chenbendataexporttaskrunnable.expiredays");
        if(StringUtil.isEmptyOrLength0(property)||!StringUtil.isNumber(property)){
            property="60";
        }
        Calendar now = Calendar.getInstance();
        now.add(Calendar.DAY_OF_MONTH, ~(Integer.parseInt(property) - 1));
        String endDate = new SimpleDateFormat("yyyyMMdd").format(now.getTime());
        String fileName = ApplicationHome.getApplicationConfig()+"/"+backdirname;
        File file= FileUtil.newFile(fileName);
        if(file.exists()){
            File[] filelist = file.listFiles();
            for (int i=0;filelist!=null&&i<filelist.length&&filelist.length>60;i++){
                Integer filename=Integer.parseInt( file.listFiles()[0].getName().substring(0,8));
                if (filename<=Integer.parseInt(endDate)){
                    FileUtil.del(filelist[i]);
                }else {
                    continue;
                }
            }
        }
    }

    
    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
    
        Map<String, TaskScheduler> taskSchedulerMap = event.getApplicationContext().getBeansOfType(TaskScheduler.class);
        TaskScheduler schedulingTaskExecutor = null;
        if(taskSchedulerMap!=null&&taskSchedulerMap.size()>0){
            schedulingTaskExecutor = taskSchedulerMap.values().iterator().next();
        }else{
            schedulingTaskExecutor=zThreadPoolTaskSchedulerDev();
            ConfigurableApplicationContext context= (ConfigurableApplicationContext)event.getApplicationContext();
        }
        CronTask cronTask1=new CronTask(this,"0 0 */6 * * ?");
        schedulingTaskExecutor.schedule(cronTask1.getRunnable(),cronTask1.getTrigger());
        log.error("自动备份devtools配置"+cronTask1.getExpression());
        return;
    }
    
    public static ThreadPoolTaskScheduler zThreadPoolTaskSchedulerDev() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(1);
//        threadPoolTaskScheduler.getScheduledThreadPoolExecutor().setMaximumPoolSize(Integer.MAX_VALUE);
        threadPoolTaskScheduler.setDaemon(true);
        threadPoolTaskScheduler.initialize();
        return threadPoolTaskScheduler;
    }
}
